import * as THREE from 'three';
import vertexShader from '@/shader/scanning/vertexShader.glsl';
import fragmentShader from '@/shader/scanning/fragmentShader.glsl';

export default class {
  mesh: THREE.Mesh;
  material: THREE.ShaderMaterial;
  center: { lat: number; lng: number };
  constructor(color = '#ffffff', position = { lat: 39.55, lng: 116.2 }) {
    this.center = position;
    this.createMaterial(color);
    this.createMesh();
  }
  createMaterial(color) {
    this.material = new THREE.ShaderMaterial({
      uniforms: {
        time: { value: 0 },
        opacity: { value: 1 },
        speed: { value: 1 },
        color: { value: new THREE.Color(color) },
        scaneTexture: { value: this.createTexture() }
      },
      vertexShader,
      fragmentShader,
      depthTest: false,
      transparent: true,
      blending: THREE.AdditiveBlending
    });
  }
  createMesh() {
    const { lng, lat } = this.center;
    this.mesh = new THREE.Mesh(new THREE.SphereGeometry(1100, 128, 128), this.material);
    this.mesh.renderOrder = 20;
    this.mesh.setRotationFromEuler(
      new THREE.Euler(0, (lng / 180) * Math.PI, ((lat - 90) / 180) * Math.PI, 'XYZ')
    );
  }
  update() {
    if (!this || !this.material) return;
    this.material.uniforms.time.value = (this.material.uniforms.time.value - 0.01) % 1;
  }
  setColor(color) {
    if (!this.material) return;
    this.material.uniforms.color.value = new THREE.Color(color);
  }
  createTexture() {
    var canvas = document.createElement('canvas');
    canvas.width = 1024;
    canvas.height = 1024;
    var ctx = canvas.getContext('2d');
    for (var i = 20; i > 0; i--) {
      if (ctx) {
        ctx.beginPath();
        ctx.rect(0, 10 * (20 - i), 1024, 2);
        ctx.fillStyle = `rgba(255, 255, 255, ${i / 20})`;
        ctx.fill();
      }
    }
    const texture = new THREE.Texture(canvas);
    texture.minFilter = THREE.LinearFilter;
    texture.wrapT = THREE.RepeatWrapping;
    texture.wrapS = THREE.RepeatWrapping;
    texture.needsUpdate = true;
    return texture;
  }
}
